package com.javasearch.search;

import com.javasearch.Config;
import com.javasearch.MainApplication;
import com.javasearch.index.IndexEnum;
import com.javasearch.utils.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.jar.JarEntry;

public class JarSourcesSearch {
    private static final Logger logger = LoggerFactory.getLogger(JarSourcesSearch.class);
    private static final String tempPath = FileUtil.getTempDirectoryPath() + IndexEnum.SOURCES.getIndexName() + File.separator + IndexEnum.SOURCES.getIndexName() + ".txt";

    public static void textSearch(String path, String keyWord, StringBuffer sb, Config config) {
        try {
            //读取jar包中的所有类
            Map<JarEntry, InputStream> jarEntryInputStreamMap = JarUtil.readJarFile(path, ".*.java$");
            Set<JarEntry> jarEntries = jarEntryInputStreamMap.keySet();
            List<Future<?>> futures1 = new ArrayList<>();
            for (JarEntry jarEntry : jarEntries) {
                Future<?> submit1 = MainApplication.executor.submit(() -> {
                    StringBuilder sb1 = new StringBuilder();
                    String name = jarEntry.getName();
                    String fullPath = path + "/" + name;
                    String context = TransitionFileStreamUtil.readIoToStr(jarEntryInputStreamMap.get(jarEntry));
                    AtomicInteger i = new AtomicInteger(0);
                    try {
                        StringUtil.readStrLine(context, (line) -> {
                            i.getAndIncrement();
                            //跳过空行
                            if (line.trim().isEmpty()) {
                               return;
                            }
                            if (line.contains(keyWord)) {
                                synchronized (config) {
                                    Integer searchLimit = config.getSearch().getSearchLimit();
                                    if (searchLimit == 0) {
                                        throw new SearchMaxLimitException("JarSourcesSearch搜索已达到上限");
                                    }
                                    config.getSearch().setSearchLimit(searchLimit - 1);
                                }
                                sb1.append("[text]##").append("[").append(fullPath).append("]").append("##").append("[").append(i).append("]").append("##").append("[").append(line).append("]").append("\n");
                            }
                        });
                    } catch (SearchMaxLimitException e) {

                    }
                    sb.append(sb1);
                });
                futures1.add(submit1);
            }
            ExecutorUtils.waitComplete(futures1);
        } catch (IOException e) {
            logger.error("JarSources Error textSearch ", e);
        }
    }


    public static void search(Config config) {
        String searchPath = config.getSearch().getSearchPath();
        File file = new File(tempPath);
        if (!file.exists()) {
            logger.info("java文件缓存不存在,请先执行索引");
            return;
        }
        String keyWord = config.getSearch().getSearchKey();
        StringBuffer sb = new StringBuffer();
        List<Future<?>> list = new ArrayList<>();
        try {
            ReadFileLineUtil.readFileStrLine(file, (path) -> {
                synchronized (config) {
                    Integer searchLimit = config.getSearch().getSearchLimit();
                    if (searchLimit == 0) {
                        throw new SearchMaxLimitException("JarSourcesSearch搜索已达到上限");
                    }
                }
                Future<?> jar2 = MainApplication.executor.submit(() -> {
                    textSearch(path, keyWord, sb, config);
                });
                list.add(jar2);
            });
        } catch (SearchMaxLimitException e) {
        }

        ExecutorUtils.waitComplete(list);
        //将搜索结果写入文件
        WriteFileStrUtil.writeStrLock(new File(searchPath), sb.toString(), true);
        logger.info("JarSourcesSearch-搜索结果:\n{}", sb);
    }
}
